/**
 * Carnegie Mellon University
 * School of Computer Science
 * MSIT eBusiness Technology
 * 
 * Team 8 - Infinity (2011 Spring)
 * infinity-team8@googlegroups.com
 * 
 * Professor: Jeffrey L. Eppinger
 * Program Faculty: Sujata Telang
 */

package controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import model.CustomerDAO;
import model.EmployeeDAO;
import model.FundDAO;
import model.FundPriceHistoryDAO;
import model.GlobalDAO;
import model.Model;
import model.PositionDAO;
import model.TransactionDAO;

import org.mybeans.dao.DAOException;
import org.mybeans.form.FormBeanException;
import org.mybeans.form.FormBeanFactory;

import databean.FundBean;
import databean.EmployeeBean;
import databean.FundPriceHistoryBean;
import databean.GlobalBean;
import databean.PositionBean;
import databean.TransactionBean;

import formbean.EmployeeTransitionDayForm;


public class EmployeeTransitionDayAction extends Action {
	private FormBeanFactory<EmployeeTransitionDayForm> formBeanFactory = FormBeanFactory.getInstance(EmployeeTransitionDayForm.class);

	private FundDAO					fundDAO;
	private EmployeeDAO				employeeDAO;
	private TransactionDAO			transactionDAO;
	private CustomerDAO				customerDAO;
	private PositionDAO				positionDAO;
	private FundPriceHistoryDAO		fundPriceHistoryDAO;
	private GlobalDAO				globalDAO;
	
	public EmployeeTransitionDayAction(Model model) {
		fundDAO = model.getFundDAO();
		employeeDAO = model.getEmployeeDAO();
		transactionDAO = model.getTransactionDAO();
		customerDAO = model.getCustomerDAO();
		positionDAO = model.getPositionDAO();
		fundPriceHistoryDAO = model.getFundPriceHistoryDAO();
		globalDAO = model.getGlobalDAO();
	}

	public String getName() { return "employee-transition-day.do"; }

    public String perform(HttpServletRequest request,HttpServletResponse response) {
        List<String> errors = new ArrayList<String>();
        request.setAttribute("errors",errors);
        
        //returns the existing session or null, if the session does not exist.
        HttpSession session = request.getSession(false);

        try {
        	EmployeeTransitionDayForm form = formBeanFactory.create(request);
	        request.setAttribute("form",form);

			request.setAttribute("employee",(EmployeeBean) request.getSession(false).getAttribute("employee"));
	        request.setAttribute("employeeList",employeeDAO.getEmployees());
	        
	        FundBean[] newFundList = fundDAO.getFunds();
	        request.setAttribute("fundList",newFundList);
	        
	        // If no params were passed, return with no errors so that the form will be
	        // presented (we assume for the first time).
	        if (!form.isPresent()) {
	            return "employee-transition-day.jsp";
	        }
	
	        // Any validation errors?
	        errors.addAll(form.getValidationErrors());
	        if (errors.size() != 0) {
	            return "employee-transition-day.jsp";
	        }
	
	        
	        
	        
	        //getting date "yyyy-MM-dd"
	        Calendar c = Calendar.getInstance();
	        c.set(Integer.parseInt(form.getDate().substring(0,4)),
	        		Integer.parseInt(form.getDate().substring(5,7))-1,
	        		  Integer.parseInt(form.getDate().substring(8,10)),
	        		  	0, 0, 0);
	        java.sql.Date dbDate = new java.sql.Date(c.getTimeInMillis());
	        

	        //getting all share stopping prices from form
	        FundPriceHistoryBean[] beans = new FundPriceHistoryBean[newFundList.length+1];
	        double[] prices = new double[newFundList.length+1];
	        for (int i = 1; i<=newFundList.length; i++) {
	        	
	        	if ( (request.getParameter("price" + i) == null ||
	        			request.getParameter("price" + i).length() == 0) ) {
	        		errors.add("Fund " + i + "'s price was not entered.");
	        		return "employee-transition-day.jsp";
	        	}
	        	
	        	
	        	prices[i] = Double.parseDouble(request.getParameter("price" + i));
	        	beans[i] = new FundPriceHistoryBean(Long.parseLong(i+""), dbDate);
	        	beans[i].setPrice(((long)(prices[i]*100)));
	        	
	        }
	        
	        
	        
	        //check date value
	        if ( (globalDAO.lookup("lastTradingDay")==null) ||
	           ( (globalDAO.lookup("lastTradingDay")!=null) &&
	           ( (dbDate.getTime()/100000) > (globalDAO.lookup("lastTradingDay").getDate().getTime()/100000) ) )
	           ) {

	        	
	        	
	        	//save them into FundPriceHistory table
		        try {
			        for (int i = 1; i<=newFundList.length; i++) {
			        	fundPriceHistoryDAO.create(beans[i]);
			        }	        
		        } catch (DAOException e) {
		        	errors.add(e.toString());
	        		return "employee-transition-day.jsp";
		        }
		        
		        
		        TransactionBean[] transactionList = transactionDAO.getPendingTransactions();
	
		        for (int i = transactionList.length-1; i >= 0; i--) {
		        	
		        	//deposit
		        	if (transactionList[i].getTransactionType().equals("deposit")) {
	
			        	transactionList[i].setExecuteDate(dbDate);	        		
		        		transactionDAO.modify(transactionList[i]);
		        		customerDAO.deposit(transactionList[i].getCustomerID(), transactionList[i].getAmount());
		        		
		        		//save last trading day into CustomerBean
		        		customerDAO.setLastTradingDay(transactionList[i].getCustomerID(), dbDate);
		        			        		
		        	}
		        	//sell
		        	else if (transactionList[i].getTransactionType().equals("sell")) {
	
		        		//set executeDate
		        		transactionList[i].setExecuteDate(dbDate);
		        		transactionDAO.modify(transactionList[i]);
		        		
		        		//calculate share price
		        		long sharePrice = (long)(prices[Integer.parseInt(transactionList[i].getFundID()+"")]*100);
		        		transactionList[i].setSharePrice(sharePrice);
		        				        		
		        		//calculate amount used in this transaction
		        		long amount = (transactionList[i].getShares() * sharePrice)/1000;
		        		transactionList[i].setAmount(amount);
		        		transactionDAO.modify(transactionList[i]);
		        		
		        		//increase amount from customer's account
		        		customerDAO.deposit(transactionList[i].getCustomerID(), amount);
		        		
		        		//decrease customer's position
		        		PositionBean bean = positionDAO.lookup(transactionList[i].getCustomerID(), transactionList[i].getFundID());
		        		if (bean.getShares()-transactionList[i].getShares() == 0) {
		        			positionDAO.remove(bean);
		        		} else {
			        		bean.setShares(bean.getShares()-transactionList[i].getShares());
			        		positionDAO.modify(bean);
		        		}
		        		
		        		//save last trading day into CustomerBean
		        		customerDAO.setLastTradingDay(transactionList[i].getCustomerID(), dbDate);
		        		
		        		
			        }
		        	//request check
		        	else if (transactionList[i].getTransactionType().equals("request")) {
	
			        	transactionList[i].setExecuteDate(dbDate);	        		
		        		transactionDAO.modify(transactionList[i]);
		        		customerDAO.request(transactionList[i].getCustomerID(), transactionList[i].getAmount());
		        		
		        		//save last trading day into CustomerBean
		        		customerDAO.setLastTradingDay(transactionList[i].getCustomerID(), dbDate);
		        		
			        		
			        }
		        	//buy, if customer has this fund already, lookup and add
			        //additional shares, otherwise, create new position
		        	else if (transactionList[i].getTransactionType().equals("buy")) {
	
		        		
		        		//set executeDate
		        		transactionList[i].setExecuteDate(dbDate);
		        		transactionDAO.modify(transactionList[i]);
		        		
		        		//calculate share price
		        		long sharePrice = (long)(prices[Integer.parseInt(transactionList[i].getFundID()+"")]*100);
		        		transactionList[i].setSharePrice(sharePrice);
	
		        		
		        		//calculate shares bought
		        		long shares = (long) ( ( (double)transactionList[i].getAmount() / sharePrice ) * 1000 );
		        		transactionList[i].setShares(shares);
		        		
	
		        		//calculate amount used in this transaction
		        		long amount = (shares * sharePrice)/1000;
		        		transactionList[i].setAmount(amount);
		        		transactionDAO.modify(transactionList[i]);
	
		        		
		        		//deduct amount from customer's account
		        		customerDAO.request(transactionList[i].getCustomerID(), amount);
		        		
		        		//increase customer's position
		        		if (shares > 0) {
			        		if (positionDAO.lookup(transactionList[i].getCustomerID(), transactionList[i].getFundID())!=null) {
			        			PositionBean bean = positionDAO.lookup(transactionList[i].getCustomerID(), transactionList[i].getFundID());
			        			bean.setShares(bean.getShares()+shares);
			        			positionDAO.modify(bean);
			        		} else {
			        			PositionBean bean = new PositionBean(transactionList[i].getCustomerID(), transactionList[i].getFundID());
			        			bean.setShares(shares);
			        			positionDAO.create(bean);
			        		}
		        		}
		        		
		        		//save last trading day into CustomerBean
		        		customerDAO.setLastTradingDay(transactionList[i].getCustomerID(), dbDate);
		        		
		        		
			        }
		        	
		        }
		        
		        //save last trading day into GlobalBean
	    		if (globalDAO.lookup("lastTradingDay")==null) {
	    			GlobalBean global = new GlobalBean("lastTradingDay");
	    			global.setDate(dbDate);
	    			globalDAO.create(global);
	    		} else {
	    			GlobalBean global = globalDAO.lookup("lastTradingDay");
	    			global.setDate(dbDate);
	    			globalDAO.modify(global);
	    		}
	    		
	    		
	        } else {
	        	errors.add("The transition date you enter needs to be greater than the date of previously ended trading day.");
        		return "employee-transition-day.jsp";
	        }
	        
	        
	        EmployeeBean[] newEmployeeList = employeeDAO.getEmployees();
	        session.setAttribute("employeeList",newEmployeeList);
	
	        // After successful registration (and login) send to...
	        String redirectTo = (String) session.getAttribute("redirectTo");
	        if (redirectTo != null) return redirectTo;
	        
			request.setAttribute("message","Execution has been done successfully!");
	        return "employee-success.jsp";
        } catch (DAOException e) {
        	errors.add(e.getMessage());
        	return "employee-transition-day.jsp";
        } catch (FormBeanException e) {
        	errors.add(e.getMessage());
        	return "employee-transition-day.jsp";
        } catch (NumberFormatException e) {
        	errors.add(e.getMessage());
        	return "employee-transition-day.jsp";
        }
    }
}
